const RetailInvestor = require('./RetailInvestor');
const MarketMaker = require('./MarketMaker');
const InstitutionalInvestor = require('./InstitutionalInvestor');
const RandomStrategy = require('../strategies/RandomStrategy');
const TrendFollowingStrategy = require('../strategies/TrendFollowingStrategy');
const MeanReversionStrategy = require('../strategies/MeanReversionStrategy');
const GamblerStrategy = require('../strategies/GamblerStrategy');
const HerdBehaviorStrategy = require('../strategies/HerdBehaviorStrategy');
const { v4: uuidv4 } = require('uuid');

/**
 * 投资者生成器
 * 根据配置生成不同类型的投资者
 */
class InvestorGenerator {
  /**
   * 创建投资者生成器实例
   * @param {Object} config - 配置对象
   */
  constructor(config = {}) {
    this.config = {
      investorTypes: [
        { type: 'RetailInvestor', weight: 0.7 },
        { type: 'MarketMaker', weight: 0.2 },
        { type: 'InstitutionalInvestor', weight: 0.1 }
      ],
      strategyDistribution: {
        RetailInvestor: [
          { strategy: 'RandomStrategy', weight: 0.4 },
          { strategy: 'TrendFollowingStrategy', weight: 0.3 },
          { strategy: 'MeanReversionStrategy', weight: 0.2 },
          { strategy: 'GamblerStrategy', weight: 0.1 }
        ],
        MarketMaker: [
          { strategy: 'RandomStrategy', weight: 1.0 }
        ],
        InstitutionalInvestor: [
          { strategy: 'TrendFollowingStrategy', weight: 0.5 },
          { strategy: 'MeanReversionStrategy', weight: 0.5 }
        ]
      },
      ...config
    };
  }

  /**
   * 生成投资者
   * @param {string} investorId - 投资者ID
   * @returns {Investor} 投资者实例
   */
  generateInvestor(investorId) {
    // 如果没有提供investorId，则生成一个UUID
    if (!investorId) {
      investorId = uuidv4();
    }
    
    const investorType = this.selectInvestorType();
    
    switch (investorType) {
      case 'RetailInvestor':
        return this.createRetailInvestor(investorId);
      case 'MarketMaker':
        return this.createMarketMaker(investorId);
      case 'InstitutionalInvestor':
        return this.createInstitutionalInvestor(investorId);
      default:
        return this.createRetailInvestor(investorId);
    }
  }

  /**
   * 根据权重分布选择投资者类型
   * @returns {String} 投资者类型
   */
  selectInvestorType() {
    // 计算总权重
    const totalWeight = this.config.investorTypes.reduce((sum, item) => sum + item.weight, 0);
    
    // 如果总权重为0，返回散户投资者
    if (totalWeight <= 0) {
      return 'RetailInvestor';
    }
    
    // 生成随机数
    const random = Math.random() * totalWeight;
    
    // 根据权重选择投资者类型
    let cumulativeWeight = 0;
    for (const item of this.config.investorTypes) {
      cumulativeWeight += item.weight;
      if (random <= cumulativeWeight) {
        return item.type;
      }
    }
    
    // 默认返回第一个类型
    return this.config.investorTypes[0].type;
  }

  /**
   * 创建散户投资者
   * @param {string} investorId - 投资者ID
   * @returns {RetailInvestor} 散户投资者实例
   */
  createRetailInvestor(investorId) {
    // 如果没有提供investorId，则生成一个UUID
    if (!investorId) {
      investorId = uuidv4();
    }
    
    // 根据策略分布选择策略
    const strategyType = this.selectStrategy(this.config.strategyDistribution.RetailInvestor);
    let strategy = null;
    
    switch (strategyType) {
      case 'RandomStrategy':
        strategy = new RandomStrategy();
        break;
      case 'TrendFollowingStrategy':
        strategy = new TrendFollowingStrategy();
        break;
      case 'MeanReversionStrategy':
        strategy = new MeanReversionStrategy();
        break;
      case 'GamblerStrategy':
        strategy = new GamblerStrategy();
        break;
      case 'HerdBehaviorStrategy':
        strategy = new HerdBehaviorStrategy();
        break;
      default:
        strategy = new RandomStrategy();
    }
    
    return new RetailInvestor({
      id: investorId,
      name: `散户${investorId.substring(0, 8)}`,
      capital: 50000 + Math.random() * 100000, // 5万到15万之间的随机资本
      strategy: strategy
    });
  }

  /**
   * 创建做市商
   * @param {string} investorId - 投资者ID
   * @returns {MarketMaker} 做市商实例
   */
  createMarketMaker(investorId) {
    // 如果没有提供investorId，则生成一个UUID
    if (!investorId) {
      investorId = uuidv4();
    }
    
    // 做市商使用随机策略
    const strategy = new RandomStrategy();
    
    return new MarketMaker({
      id: investorId,
      name: `做市商${investorId.substring(0, 8)}`,
      capital: 1000000 + Math.random() * 2000000, // 100万到300万之间的随机资本
      strategy: strategy
    });
  }

  /**
   * 创建机构投资者
   * @param {string} investorId - 投资者ID
   * @returns {InstitutionalInvestor} 机构投资者实例
   */
  createInstitutionalInvestor(investorId) {
    // 如果没有提供investorId，则生成一个UUID
    if (!investorId) {
      investorId = uuidv4();
    }
    
    // 机构投资者使用趋势跟踪或均值回归策略
    const strategyType = this.selectStrategy(this.config.strategyDistribution.InstitutionalInvestor);
    let strategy = null;
    
    switch (strategyType) {
      case 'TrendFollowingStrategy':
        strategy = new TrendFollowingStrategy();
        break;
      case 'MeanReversionStrategy':
        strategy = new MeanReversionStrategy();
        break;
      default:
        strategy = new TrendFollowingStrategy();
    }
    
    return new InstitutionalInvestor({
      id: investorId,
      name: `机构投资者${investorId.substring(0, 8)}`,
      capital: 10000000 + Math.random() * 20000000, // 1000万到3000万之间的随机资本
      strategy: strategy
    });
  }

  /**
   * 根据权重分布选择策略
   * @param {Array} strategyDistribution - 策略分布数组
   * @returns {String} 策略类型
   */
  selectStrategy(strategyDistribution) {
    if (!strategyDistribution || strategyDistribution.length === 0) {
      return 'RandomStrategy';
    }
    
    // 计算总权重
    const totalWeight = strategyDistribution.reduce((sum, item) => sum + item.weight, 0);
    
    // 如果总权重为0，返回随机策略
    if (totalWeight <= 0) {
      return 'RandomStrategy';
    }
    
    // 生成随机数
    const random = Math.random() * totalWeight;
    
    // 根据权重选择策略
    let cumulativeWeight = 0;
    for (const item of strategyDistribution) {
      cumulativeWeight += item.weight;
      if (random <= cumulativeWeight) {
        return item.strategy;
      }
    }
    
    // 默认返回第一个策略
    return strategyDistribution[0].strategy;
  }
}

module.exports = InvestorGenerator;